;int generar_codificacion(unsigned char *src_buf, unsigned int src_size, unsigned char *dst_buf, unsigned int dst_size, codigo_t *tabla_codigos)

%include "macros/codigo_t.mac"

global generar_codificacion

%define ptr_dst_buf_actual [ebp - 4]
%define ptr_src_buf [ebp + 8]
%define src_size [ebp + 12]
%define ptr_dst_buf [ebp + 16]
%define dst_size [ebp + 20]
%define ptr_tabla_codigos [ebp + 24]

section .text

generar_codificacion:
	push ebp
	mov ebp, esp
	sub esp, 4
	push esi
	push edi
	push ebx
	
	xor ecx, ecx ; ecx = contador de bytes del src_buf.
	xor ebx, ebx ; ebx = simbolo.
	xor edx, edx ; edx = acumulador de codigos.
	xor edi, edi ; edi = contador de bits de edx.
	mov eax, ptr_dst_buf
	mov ptr_dst_buf_actual, eax ; Inicializamos ptr_dst_buf_actual.
	mov esi, ptr_src_buf ; esi = puntero al src_buf.
	
	; Levanta del src_buf los simbolos, obtiene la codificacion y la agrega al registro edx.
	; Cuando completa los 32 bits del registro edx, mueve el contenido al dst_buf.
ciclo:
	mov bl, [esi + ecx] ; bl = simbolo.
	push esi ; Guardamos el puntero el src_buf.
	push ecx ; Guardamos el contador en bytes del src_buf.
	
	mov esi, ptr_tabla_codigos ; esi = puntero a la tabla de codigos.
	
	shl ebx, 4 ; Multiplicamos el simbolo por 16 para indexar la tabla de codigos.
	mov eax, [esi + ebx + off_codigo_rev_cod] ; eax = codigo reverso.
	mov ecx, [esi + ebx + off_long_codigo_cod] ; ecx = long del codigo.
	shr ebx, 4 ; Restauramos el simbolo.
	
ciclo2:	; Va agregando de a 1 bit el codigo en edx.
	rcr eax, 1
	rcl edx, 1
	inc edi
	
	cmp edi, 32
	jne sigo
	
	push eax
ciclo3:	; Cuando se llena edx se da vuelta todo el bloque de 32 bits y se lo guarda en el dst_buf.
	rcr edx, 1
	rcl eax, 1
	dec edi
	cmp edi, 0
	jne ciclo3
	
	mov esi, ptr_dst_buf_actual
	mov [esi], eax
	add dword ptr_dst_buf_actual, 4
	xor edi, edi
	xor edx, edx
	pop eax
	
sigo:
	loop ciclo2
	pop ecx
	pop esi
	
	inc ecx
	cmp ecx, src_size ; ecx = tamaño en bytes del src_buf.
	je termine
	jmp ciclo
	
termine:
	xor eax, eax ; La funcion termino con exito se retorna el valor cero.
	cmp edi, 0 ; Nos fijamos si no quedaron datos en el registro edx.
	je fin
	mov esi, ptr_dst_buf_actual
	
ciclo5: ; Como quedaron datos se agrega basura al final para completar los 32 bits de edx.
	shl edx, 1
	inc edi
	cmp edi, 32
	jne ciclo5
	
ciclo4: ; Cuando se llena edx se da vuelta todo el bloque de 32 bits y se lo guarda en el dst_buf.
	rcr edx, 1
	rcl eax, 1
	dec edi
	cmp edi, 0
	jne ciclo4
	
	mov [esi], eax
	xor eax, eax ; La funcion termino con exito se retorna el valor cero.
	
fin:
	pop ebx
	pop edi
	pop esi
	add esp, 4
	pop ebp
	ret
